// 处理用户认证相关业务逻辑（注册、登录、获取当前用户信息）

// 导入User数据模型（用于操作数据库中的用户表）
const { User } = require('../models');
// 导入JWT生成工具函数（用于生成身份令牌）
const { generateToken } = require('../utils/jwt');
// 导入Joi（用于验证前端传递的请求数据格式）
const Joi = require('joi');
// 导入Sequelize的Op操作符（用于构建复杂查询条件）
const { Op } = require('sequelize');

/**
 * 定义用户注册数据的验证规则
 * 用于校验前端传递的注册信息是否符合要求
 */
const registerSchema = Joi.object({
  // 用户名：必填项，字符串类型，长度2-50个字符
  username: Joi.string().required().min(2).max(50),
  // 密码：必填项，字符串类型，长度5-30个字符
  password: Joi.string().required().min(5).max(30),
});

/**
 * 定义用户登录数据的验证规则
 * 用于校验前端传递的登录信息是否符合要求
 */
const loginSchema = Joi.object({
  // 用户名：必填项（登录时只需验证存在性，无需验证长度，因注册时已限制）
  username: Joi.string().required(),
  // 密码：必填项（同理，注册时已验证长度）
  password: Joi.string().required(),
});

/**
 * 用户注册接口处理函数
 * 对应路由：POST /api/auth/register
 * 功能：接收前端注册数据，验证合法性，创建用户并返回令牌
 */
const register = async (req, res, next) => {
  try {
    // 验证前端传递的注册数据是否符合预设规则
    const { error } = registerSchema.validate(req.body);
    if (error) {
      // 验证失败：返回400状态码（请求参数错误）和具体错误信息
      return res.status(400).json({ message: error.details[0].message });
    }

    // 从请求体中提取注册数据（用户名和密码）
    const { username, password } = req.body;

    // 检查用户名是否已被注册（避免重复注册）
    const existingUser = await User.findOne({
      where: {
        // 使用Op.or构建查询条件（当前仅检查用户名）
        [Op.or]: [{ username }],
      },
    });

    //若用户名已存在，返回400错误提示
    if (existingUser) {
      return res.status(400).json({ message: '该用户名已被其他用户占用' });
    }

    // 注册数据合法，创建新用户（调用User模型方法，Sequelize会自动加密密码，看user.model.js的钩子）
    const user = await User.create({
      username,
      password, //这里传递的密码是明文，但是模型的beforeCreate钩子会自动加密
    });

    // 生成JWT令牌，（用户注册成功后，直接登录，不用再输入密码）
    // 令牌中包含用户ID，用于后续身份验证
    const token = generateToken(user.userId);

    // 返回成功响应
    // 状态码201表示资源创建成功，返回令牌和用户基本信息（不含密码）
    res.status(201).json({
      message: '用户注册成功',
      token, // 生成的JWT令牌
      user: {
        id: user.id, // 用户ID
        username: user.username, // 用户名
      },
    });
  } catch (error) {
    // 捕获异常：将错误传递给全局错误处理中间件
    next(error);
  }
};

/**
 * 用户登录接口处理函数
 * 对应路由：POST /api/auth/login
 * 功能：验证用户身份，生成并返回JWT令牌
 */
const login = async (req, res, next) => {
  try {
    //  验证前端传递的登录数据是否符合预设规则
    const { error } = loginSchema.validate(req.body);
    if (error) {
      // 验证失败：返回400状态码和错误信息
      return res.status(400).json({ message: error.details[0].message });
    }

    // 从请求体中提取登录数据（用户名和密码）
    const { username, password } = req.body;

    // 根据用户名查询用户是否存在
    const user = await User.findOne({ where: { username } });
    if (!user) {
      // 用户不存在：返回401状态码（未授权）
      return res.status(401).json({ message: '该用户不存在' });
    }

    // 验证密码是否正确（调用user.model.js的validatePassword方法）
    // 该方法会对比明文密码与数据库中存储的加密密码
    const isPasswordValid = await user.validatePassword(password);
    if (!isPasswordValid) {
      // 密码错误 → 返回401错误
      return res.status(401).json({ message: '密码输入错误' });
    }

    // 登录成功 → 生成JWT令牌
    const token = generateToken(user.userId);

    // 返回登录成功响应
    // 状态码200表示请求成功，返回令牌和用户基本信息
    res.status(200).json({
      message: '登录成功',
      token, // JWT令牌
      user: {
        id: user.id,
        username: user.username,
      },
    });
  } catch (error) {
    // 捕获异常：传递给全局错误处理中间件
    next(error);
  }
};

/**
 * 获取当前登录用户信息接口处理函数
 * 对应路由：GET /api/auth/me
 * 功能：返回当前已登录用户的基本信息（需先通过认证中间件验证）
 */
const getCurrentUser = async (req, res, next) => {
  try {
    // req.user由认证中间件（如protect）在验证令牌后挂载
    // 包含当前登录用户的信息（已排除密码等敏感字段）
    res.status(200).json({
      user: req.user,
    });
  } catch (error) {
    // 捕获异常：传递给全局错误处理中间件
    next(error);
  }
};

// 导出认证相关的控制器函数（供路由模块调用）
module.exports = {
  register,
  login,
  getCurrentUser,
};
